package jdir.util;

import org.apache.commons.logging.Log;

/**
 * Helperclass for logging, to get through the actual thread the name of the actual method 
 */
public class LogUtil
{
	/**
	 * Number of the stackframe in which the actual calling method lays<br>
	 * 0: getStackTrace() <br/>
	 * ?: currentThread() <br/>
	 * 1: getMethodName() <br/>
	 * 2: begin/end <br/>
	 * 3: calling method <br/>
	 * For JDK 5.0 currentThread() will although be counted
	 */
	private static final int	STACK_NUMBER;
	static
	{
		int stackNumber = 4;
		try
		{
			Class.forName("java.lang.Enum"); // available since JDK 5.0
		} catch (ClassNotFoundException e)
		{
			throw new IllegalStateException("At least JDK 5.0 is required");
		}

		try
		{
			Class.forName("java.io.Console"); // available since JDK 6.0
			stackNumber = 3;
		} catch (ClassNotFoundException e)
		{
			// JDK 5.0 but not JDK 6.0
		}

		STACK_NUMBER = stackNumber;
	}

	private static final String	BEGIN	= MessagesUtil.getMessage("log.begin") + ' ';
	private static final String	END		= MessagesUtil.getMessage("log.end") + ' ';

	/**
	 * This method will be called when ever it's useful to see in the logfile that a method has been called
	 * @param log log-object
	 * @param args additional arguments which will be seperated by a "," in the logfile
	 */
	public static void begin(Log log, Object... args)
	{
		final String methodName = getMethodName();
		final StringBuilder sb = new StringBuilder(BEGIN + methodName);
		final int anzahlArgs = args.length;
		if (anzahlArgs > 0)
		{
			sb.append(": ");
			for (int i = 0; i < anzahlArgs; i++)
			{
				sb.append(args[i]);
				sb.append(", ");
			}
			final int laenge = sb.length();
			sb.delete(laenge - 2, laenge - 1);
		}
		log.debug(sb.toString());
	}

	/**
	 * This method will be called when ever it's useful to see in the logfile that a called method has been left
	 * @param log log-object
	 * @param args additional arguments which will be seperated by a "," in the logfile
	 */
	public static void end(Log log, Object... args)
	{
		final String methodName = getMethodName();
		final StringBuilder sb = new StringBuilder(END + methodName);
		final int anzahlArgs = args.length;
		if (anzahlArgs > 0)
		{
			sb.append(": ");
			for (int i = 0; i < anzahlArgs; i++)
			{
				sb.append(args[i]);
				sb.append(", ");
			}
			final int laenge = sb.length();
			sb.delete(laenge - 2, laenge - 1);
		}
		log.debug(sb.toString());
	}

	/**
	 * This method will be called when ever it's useful to see in the logfile that a called method has been left with an error
	 * @param log log-object
	 * @param e thrown exception
	 */
	public static void endError(Log log, Exception e)
	{
		log.error(END + getMethodName() + ": " + e.getMessage());
	}

	/**
	 * This method will be called when ever it's useful to see in the logfile that a called method has been left with a warning
	 * @param log log-object
	 * @param e thrown exception
	 */
	public static void endWarn(Log log, Exception e)
	{
		log.warn(END + getMethodName() + ": " + e.getMessage());
	}

	/**
	 * @return Name of the calling method
	 * @see LogUtil#STACK_NUMBER
	 */
	private static String getMethodName()
	{
		final StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
		return stackTraceElements[STACK_NUMBER].getMethodName();
	}
}
